import wx
import wx.lib.masked as masked
from time import time
from types import UnicodeType, StringType, LongType, IntType
from LMG.GUI.Base.menu import Menu
from LMG.Utility.constants import *
from LMG.GUI.Base.ArtManager import ArtManager

class CommandSchedulerDialog(wx.Dialog):
    STATUS = 0
    FREQUENCY = 1
    DATE = 2
    TIME = 3
    ENDDATE = 4
    COMMAND = 5
    VALUE = 6   
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, -1, _("Command Scheduler"))
        self.commandscheduler = utility.frame.commandScheduler        
                
        sizer = wx.BoxSizer(wx.VERTICAL)

        # Commands list
        commandsSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Scheduler Commands')), wx.VERTICAL)
        self.commandlist = wx.ListCtrl(self, -1, size = (735, 200), style = wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
        self.commandlist.InsertColumn(self.STATUS, _('Status'))
        self.commandlist.SetColumnWidth(self.STATUS, 50)
        self.commandlist.InsertColumn(self.FREQUENCY, _('Frequency'))
        self.commandlist.SetColumnWidth(self.FREQUENCY, 150)
        self.commandlist.InsertColumn(self.DATE, _('Date'))
        self.commandlist.SetColumnWidth(self.DATE, 70)
        self.commandlist.InsertColumn(self.TIME, _('Time'))
        self.commandlist.SetColumnWidth(self.TIME, 60)
        self.commandlist.InsertColumn(self.ENDDATE, _('Expires on'))
        self.commandlist.SetColumnWidth(self.ENDDATE, 70)
        self.commandlist.InsertColumn(self.COMMAND, _('Command'))
        self.commandlist.SetColumnWidth(self.COMMAND, 250)
        self.commandlist.InsertColumn(self.VALUE, _('Value'))
        self.commandlist.SetColumnWidth(self.VALUE, 80)
        commandsSizer.Add(self.commandlist, 1, wx.ALIGN_CENTER)
        sizer.Add(commandsSizer, 1, wx.ALL, 5)

        # Scheduler options
        bottombox = wx.BoxSizer(wx.HORIZONTAL)
        self.schedautostart = wx.CheckBox(self, -1, _('Run at startup'))
        self.schedautostart.SetValue(utility.config.Read('schedautostart', "boolean"))
        bottombox.Add(self.schedautostart, 0, wx.ALIGN_CENTER_VERTICAL)
        
        self.schedrunpast = wx.CheckBox(self, -1, _('Run past commands when scheduler starts'))
        self.schedrunpast.SetValue(utility.config.Read('schedrunpast', "boolean"))
        bottombox.Add(self.schedrunpast, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
        
        bottombox.Add((0, 0), 1)        
        addbtn = wx.Button(self, wx.ID_ADD)
        bottombox.Add(addbtn, 0, wx.LEFT, 5)
        deletebtn = wx.Button(self, wx.ID_REMOVE)
        bottombox.Add(deletebtn, 0)
        sizer.Add(bottombox, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)

        # Action buttons
        buttonsbox = wx.BoxSizer(wx.HORIZONTAL)
        if self.commandscheduler.running:
            self.actionbtn = wx.Button(self, -1, _('Stop'))
        else:
            self.actionbtn = wx.Button(self, -1, _('Start'))
        buttonsbox.Add(self.actionbtn, 0, wx.ALL, 5)
        self.closebtn = wx.Button(self, wx.ID_CLOSE, _('Close'))
        self.closebtn.SetDefault()
        buttonsbox.Add(self.closebtn, 0, wx.ALL, 5)
        sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
        sizer.Add(buttonsbox, 0, wx.CENTER)

        
        # Events Table
        self.commandlist.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onRightClickList)
        self.commandlist.Bind(wx.EVT_KEY_DOWN, self.onKeyInList)
        self.schedautostart.Bind(wx.EVT_CHECKBOX, self.onAutoStartChanged)
        self.schedrunpast.Bind(wx.EVT_CHECKBOX, self.onRunPastChanged)
        self.Bind(wx.EVT_BUTTON, self.onAddSchedCommand, addbtn)
        self.Bind(wx.EVT_BUTTON, self.onDeleteSchedCommand, deletebtn)
        self.Bind(wx.EVT_BUTTON, self.onAction, self.actionbtn)
        self.Bind(wx.EVT_BUTTON, self.onClose, self.closebtn)
        self.Bind(wx.EVT_CLOSE, self.onClose)

        # Finish...
        self.SetAutoLayout(True)
        self.SetSizerAndFit(sizer)

        self.Initialize()
        self.Centre()
        
    def Initialize(self):
        """ Initialize the commands list"""

        self.commandlist.DeleteAllItems()
        
        index = 0
        for sc in self.commandscheduler.schedcommands:
            self.commandlist.InsertStringItem(index, '')
            
            # Status
            if sc.active:
                self.commandlist.SetStringItem(index, self.STATUS, _('Enabled'))
            else:
                self.commandlist.SetStringItem(index, self.STATUS, _('Disabled'))

            # Frequency
            if sc.frequency == 'daily':
                self.commandlist.SetStringItem(index, self.FREQUENCY, _('Daily from'))
            elif sc.frequency == 'weekly':
                self.commandlist.SetStringItem(index, self.FREQUENCY, _('Weekly from'))
            elif sc.frequency == 'once':
                self.commandlist.SetStringItem(index, self.FREQUENCY, _('One time on'))
            else:
                string = _('Weekly on days:')
                for i in xrange(7):
                    if sc.weekschedule[i] == '1':
                        string += str(i+1) + ','
                self.commandlist.SetStringItem(index, self.FREQUENCY, string)

            # Start Date
            dt = wx.DateTimeFromTimeT(sc.time_start)
            self.commandlist.SetStringItem(index, self.DATE, dt.FormatDate())

            # Start Time
            self.commandlist.SetStringItem(index, self.TIME, dt.FormatTime())
            
            # End Date
            if sc.time_end:
                self.commandlist.SetStringItem(index, self.ENDDATE, wx.DateTimeFromTimeT(sc.time_end).FormatDate())
            else:
                self.commandlist.SetStringItem(index, self.ENDDATE, _('None'))

            # Command
            self.commandlist.SetStringItem(index, self.COMMAND, self.commandscheduler.getCommandName(sc.command))

            # Value
            if type(sc.value) in (StringType, UnicodeType):
                self.commandlist.SetStringItem(index, self.VALUE, sc.value)
            elif type(sc.value) in (LongType, IntType) and sc.value < 0:
                self.commandlist.SetStringItem(index, self.VALUE, _("Reset"))                
            else:
                self.commandlist.SetStringItem(index, self.VALUE, str(sc.value))
            index += 1
        ArtManager.Get().MakeAlternateList(self.commandlist)
        
    def onKeyInList(self, event):
        """ keyboard shortcuts"""
        if event.ControlDown():
            keycode = event.GetKeyCode()
            if keycode == ord('a') or keycode == ord('A'):
                # Select all commands
                for index in range(self.commandlist.GetItemCount()):
                    self.commandlist.Select(index)
            elif keycode == ord('x') or keycode == ord('X'):
                # Invert command selection
                for index in range(self.commandlist.GetItemCount()):
                    self.commandlist.SetItemState(index, 4 - self.commandlist.GetItemState(index, wx.LIST_STATE_SELECTED), wx.LIST_STATE_SELECTED)
        event.Skip()
        
    def getSelected(self):
        """ get selected items """
        selected = []
        index = self.commandlist.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
        while index != -1:
            selected.append(index)
            index = self.commandlist.GetNextItem(index, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
        return selected
    
    def getClickedColumn(self, x):
        """ Returns the column number of the list from the x coordinate of a point inside the list """
        currentwidth = -self.commandlist.GetScrollPos(wx.HORIZONTAL)
        for rank in xrange(self.commandlist.GetColumnCount()):
            currentwidth += self.commandlist.GetColumnWidth(rank)
            if x < currentwidth:
                return rank
        return -1
        
    def onRightClickList(self, event):
        """ show the menu/dialog for editing properties """
        self.selectedrow =  event.GetIndex()
        col = self.getClickedColumn(event.GetPoint()[0])
        popupx, popupy = event.GetPoint() + self.commandlist.GetPosition()
        
        if col == self.STATUS:
            if not hasattr(self, "activityMenu"):
                self.activityMenu = Menu()
                self.activityMenuID = wx.NewId()
                self.activityMenu.Append(self.activityMenuID, _('Disabled '), _('Disabled'), wx.ITEM_RADIO)
                self.activityMenu.Append(self.activityMenuID+1, _('Enabled'), _('Enabled'), wx.ITEM_RADIO)
                self.Bind(wx.EVT_MENU, self.onChangeActivity, id = self.activityMenuID, id2 = self.activityMenuID+1)
            self.activityMenu.Check(int(self.commandscheduler.schedcommands[self.selectedrow].active) + self.activityMenuID, True)
            self.PopupMenuXY(self.activityMenu, popupx, popupy)
        elif col == self.FREQUENCY:
            command = self.commandscheduler.schedcommands[self.selectedrow]
            changefreqdlg = ChangeFreqDialog(self, -1, command.frequency, command.weekschedule, self.ClientToScreenXY(popupx, popupy))
            retcode = changefreqdlg.ShowModal()
            retfreq = changefreqdlg.freq
            retweeksched = changefreqdlg.weeksched
            changefreqdlg.Destroy()
            if retcode == wx.ID_OK:
                self.onChangeFreq(retfreq, retweeksched)
        elif col == self.DATE:
            changedatedlg = ChangeDateDialog(self, -1, wx.DateTimeFromTimeT(self.commandscheduler.schedcommands[self.selectedrow].time_start),
                                             self.ClientToScreenXY(popupx, popupy))
            retcode = changedatedlg.ShowModal()
            retval = changedatedlg.datetime
            changedatedlg.Destroy()
            if retcode == wx.ID_OK:
                self.onChangeDate(retval)
        elif col == self.TIME:
            changetimedlg = ChangeTimeDialog(self, -1, wx.DateTimeFromTimeT(self.commandscheduler.schedcommands[self.selectedrow].time_start),
                                             self.ClientToScreenXY(popupx, popupy))
            retcode = changetimedlg.ShowModal()
            retval = changetimedlg.datetime
            changetimedlg.Destroy()
            if retcode == wx.ID_OK:
                self.onChangeTime(retval)
        elif col == self.ENDDATE:
            if self.commandscheduler.schedcommands[self.selectedrow].frequency == 'once':
                return
            edt = self.commandscheduler.schedcommands[self.selectedrow].time_end
            if edt:
                edt = wx.DateTimeFromTimeT(edt)
            else:
                edt = None
            changeenddatedlg = ChangeEndDateDialog(self, -1, edt, self.ClientToScreenXY(popupx, popupy))
            retcode = changeenddatedlg.ShowModal()
            retval = changeenddatedlg.datetime
            changeenddatedlg.Destroy()
            if retcode == wx.ID_OK:
                self.onChangeEndDate(retval)
        elif col == self.COMMAND:
            commands = self.commandscheduler.commandsList
            if not hasattr(self, "commandMenu"):
                self.commandMenu = Menu()
                self.commandMenuID = wx.NewId()
                for i in xrange(len(self.commandscheduler.commandsList)):
                    self.commandMenu.Append(self.commandMenuID + i,
                                            self.commandscheduler.getCommandName(self.commandscheduler.commandsList[i]),
                                            self.commandscheduler.getCommandName(self.commandscheduler.commandsList[i]),
                                            wx.ITEM_RADIO)                
                self.Bind(wx.EVT_MENU, self.onChangeCommand, id = self.commandMenuID, id2 = self.commandMenuID + len(self.commandscheduler.commandsList) - 1)
            self.commandMenu.Check(self.commandscheduler.commandsList.index(self.commandscheduler.schedcommands[self.selectedrow].command) + self.commandMenuID, True)
            self.PopupMenuXY(self.commandMenu, popupx, popupy)
        elif col == self.VALUE:
            selected = self.getSelected()
            
            firstcommand = self.commandscheduler.schedcommands[selected[0]].command
            for index in selected[1:]:
                if self.commandscheduler.schedcommands[index].command != firstcommand:
                    return
            command = self.commandscheduler.schedcommands[self.selectedrow].command
            valueType = self.commandscheduler.getCommandValueType(command)
            if valueType == int:
                changevaluedlg = ChangeValueDialog(self, -1, int(self.commandscheduler.schedcommands[self.selectedrow].value),
                                                   self.ClientToScreenXY(popupx, popupy))
                retcode = changevaluedlg.ShowModal()
                retval = changevaluedlg.value
                changevaluedlg.Destroy()
                if retcode == wx.ID_OK:
                    self.onChangeValueNumber(retval)
            elif valueType == bool:
                if not hasattr(self, "boolMenu"):
                    self.boolMenu = Menu()
                    self.boolMenuID = wx.NewId()
                    self.boolMenu.Append(self.boolMenuID, _("Disabled"), _("Disabled"), wx.ITEM_RADIO)
                    self.boolMenu.Append(self.boolMenuID+1, _("Enabled"), _("Enabled"), wx.ITEM_RADIO)
                    self.Bind(wx.EVT_MENU, self.onChangeValue, id = self.boolMenuID, id2 = self.boolMenuID+1)
                    if self.commandscheduler.schedcommands[self.selectedrow].value == "1":
                        self.boolMenu.Check( self.boolMenuID+1, True)
                    else:
                        self.boolMenu.Check( self.boolMenuID, True)
                self.PopupMenuXY(self.boolMenu, popupx, popupy)
        else:
            event.Skip()

    def onChangeActivity(self, event):
        now = time()
        change = False
        newactivity = bool(event.GetId() - self.activityMenuID)
        for index in self.getSelected():
            if self.commandscheduler.schedcommands[index].active != newactivity:
                self.commandscheduler.schedcommands[index].active = newactivity
                if newactivity:
                    self.commandlist.SetStringItem(index, 0, _('Enabled'))
                else:
                    self.commandlist.SetStringItem(index, 0, _('Disabled'))
                change = True
        if change and self.commandscheduler.running:
            self.commandscheduler.scheduleNext(now)
    
    def onChangeFreq(self, newfreq, newweeksched):
        now = time()
        change = False
        for index in self.getSelected():
            if self.commandscheduler.schedcommands[index].frequency != newfreq:
                self.commandscheduler.schedcommands[index].frequency = newfreq
                if self.commandscheduler.schedcommands[index].weekschedule != newweeksched:
                    self.commandscheduler.schedcommands[index].weekschedule = newweeksched
                if newfreq == 'once':
                    # Reset end date to None
                    self.commandscheduler.schedcommands[index].enddate = 0
                    self.commandlist.SetStringItem(index, self.ENDDATE, _('None'))
                    strweeksched = _('One time on')
                elif newfreq == 'daily':
                    strweeksched = _('Daily from') 
                elif newfreq == 'weekly':
                    strweeksched = _('Weekly from')
                else:
                    strweeksched = _('Weekly on days:')
                    for i in xrange(7):
                        if self.commandscheduler.schedcommands[index].weekschedule[i] == '1':
                            strweeksched += str(i+1) + ','
                change = True
            elif self.commandscheduler.schedcommands[index].weekschedule != newweeksched:
                self.commandscheduler.schedcommands[index].weekschedule = newweeksched
                if newfreq == 'weekly':
                    change = True
                    strweeksched = _('Weekly from')
                elif newfreq == 'weeklymulti':
                    change = True
                    strweeksched = _('Weekly on days:')
                    for i in xrange(7):
                        if self.commandscheduler.schedcommands[index].weekschedule[i] == '1':
                            strweeksched += str(i+1) + ','
            if change:
                self.commandlist.SetStringItem(index, self.FREQUENCY, strweeksched)
                if self.commandscheduler.running:
                    self.commandscheduler.schedcommands[index].computeNextRunTime(now)
                    self.commandscheduler.schedcommands[index].changed = True
        if change and self.commandscheduler.running:
            self.commandscheduler.scheduleNext(now)

    def onChangeDate(self, newdate):
        now = time()
        change = False
        for index in self.getSelected():
            currentdate = wx.DateTimeFromTimeT(self.commandscheduler.schedcommands[index].time_start)
            if not newdate.IsSameDate(currentdate):
                # If date has really changed
                currentdate.SetYear(newdate.GetYear())
                currentdate.SetMonth(newdate.GetMonth())
                currentdate.SetDay(newdate.GetDay())
                self.commandscheduler.schedcommands[index].time_start = currentdate.GetTicks()
                self.commandlist.SetStringItem(index, self.DATE, currentdate.FormatDate())
                if self.commandscheduler.running:
                    self.commandscheduler.schedcommands[index].computeNextRunTime(now)
                    self.commandscheduler.schedcommands[index].changed = True
                change = True
        if change:
            self.sortCommands()
            if self.commandscheduler.running:
                self.commandscheduler.scheduleNext(now)
    
    def onChangeTime(self, newtime):
        now = time()
        change = False
        for index in self.getSelected():
            currenttime = wx.DateTimeFromTimeT(self.commandscheduler.schedcommands[index].time_start)
            if not newtime.IsSameTime(currenttime):
                # If time has really changed
                currenttime.SetHour(newtime.GetHour())
                currenttime.SetMinute(newtime.GetMinute())
                currenttime.SetSecond(newtime.GetSecond())
                self.commandscheduler.schedcommands[index].time_start = currenttime.GetTicks()
                self.commandlist.SetStringItem(index, self.TIME, currenttime.FormatTime())
                if self.commandscheduler.running:
                    self.commandscheduler.schedcommands[index].computeNextRunTime(now)
                    self.commandscheduler.schedcommands[index].changed = True
                change = True
        if change:
            self.sortCommands()
            if self.commandscheduler.running:
                self.commandscheduler.scheduleNext(now)

    def onChangeEndDate(self, newdate):
        now = time()
        change = False
        if newdate == None:
            newdate = 0
        else:
            newdate = newdate.GetTicks()
        for index in self.getSelected():
            if self.commandscheduler.schedcommands[index].frequency == 'once':
                continue
            if newdate != self.commandscheduler.schedcommands[index].time_end:
                # If date has really changed
                self.commandscheduler.schedcommands[index].time_end = newdate
                if newdate:
                    self.commandlist.SetStringItem(index, self.ENDDATE, wx.DateTimeFromTimeT(newdate).FormatDate())
                else:
                    self.commandlist.SetStringItem(index, self.ENDDATE, _('None'))
                self.commandscheduler.schedcommands[index].computeNextRunTime(now)
                change = True
        if change:
            self.commandscheduler.scheduleNext(now)
    
    def onChangeCommand(self, event):
        
        now = time()
        rescheduleneeded = False
        newcom = self.commandscheduler.commandsList[event.GetId() - self.commandMenuID]
        for index in self.getSelected():
            if newcom != self.commandscheduler.schedcommands[index].command:
                # If command has really changed
                if newcom == 'none' or self.commandscheduler.schedcommands[index].command == 'none':
                    rescheduleneeded = True
                self.commandscheduler.schedcommands[index].command = newcom
                self.commandlist.SetStringItem(index, self.COMMAND, self.commandscheduler.getCommandName(newcom))
                valueType = self.commandscheduler.getCommandValueType(newcom)
                if valueType == int or valueType == bool:
                    self.commandscheduler.schedcommands[index].value = '0'
                    self.commandlist.SetStringItem(index, self.VALUE, '0')
                else:
                    self.commandscheduler.schedcommands[index].value = '---'
                    self.commandlist.SetStringItem(index, self.VALUE, '---')
        if rescheduleneeded and self.commandscheduler.running:
            self.commandscheduler.scheduleNext(now)

    def onChangeValue(self, event):
        value = bool(event.GetId() - self.boolMenuID)
        if value:        
            strvalue = "1"
        else:
            strvalue = "0"
        for index in self.getSelected():
            self.commandscheduler.schedcommands[index].value = strvalue
            self.commandlist.SetStringItem(index, self.VALUE, strvalue)

    
    def onChangeValueNumber(self, value):
        strvalue = str(value)
        for index in self.getSelected():
            self.commandscheduler.schedcommands[index].value = strvalue
            self.commandlist.SetStringItem(index, self.VALUE, strvalue)
    
    def onAddSchedCommand(self, event):
        """ add command """
        newcommand, index = self.commandscheduler.newCommand()
        self.Initialize()
        self.commandlist.Select(index)
        self.commandlist.SetFocus()
    
    def onDeleteSchedCommand(self, event):
        """ remove command """
        now = time()
        tobedeleted = self.getSelected()
        tobedeleted.reverse()
        for index in tobedeleted:
            del self.commandscheduler.schedcommands[index]
            self.commandlist.DeleteItem(index)
        ArtManager.Get().MakeAlternateList(self.commandlist)
        self.commandlist.SetFocus()
        if self.commandscheduler.running:
            self.commandscheduler.scheduleNext(now)

    def onAction(self, event):
        """ stop/start the command scheduler"""
        if self.commandscheduler.running:
            try:
                self.actionbtn.SetLabel(_('Start'))
            except:
                pass
            self.commandscheduler.stop()
        else:
            self.actionbtn.SetLabel(_('Stop'))
            self.commandscheduler.start()
        self.commandscheduler.save()
        utility.actions[ACTION_CMDSCHEDULER].updateButton()

    def sortCommands(self):
        """ sort command according to their start time """
        self.sortcol = []
        nbitem = len(self.commandscheduler.schedcommands)
        for index in range(nbitem):
            self.sortcol.append(self.commandscheduler.schedcommands[index].time_start)
            self.commandlist.SetItemData(index, index)
        self.commandlist.SortItems(self.sortList)
        schedcommands2 = self.commandscheduler.schedcommands[:]
        del self.commandscheduler.schedcommands[:]
        for index in range(nbitem):
            self.commandscheduler.schedcommands.append(schedcommands2[self.commandlist.GetItemData(index)])

    def sortList(self, item1, item2):
        """ generic function to sort listctrl """
        if self.sortcol[item1] < self.sortcol[item2]:
            return -1
        if self.sortcol[item1] > self.sortcol[item2]:
            return 1
        return 0

    def onAutoStartChanged(self, event):
        utility.config.Write('schedautostart', self.schedautostart.GetValue(), "boolean")
        utility.config.Flush()
        
    def onRunPastChanged(self, event):
        utility.config.Write('schedrunpast', self.schedrunpast.GetValue(), "boolean")
        utility.config.Flush()

    def onClose(self, event):
        """ close dialog """
        self.commandscheduler.save()
        self.EndModal(wx.ID_OK)
        event.Skip()
        
class ChangeFreqDialog(wx.Dialog):
    def __init__(self, parent, ID, freq, weeksched, pos):
        pre = wx.PreDialog()
        pre.Create(parent, ID, '', pos, (-1, -1), wx.DEFAULT_DIALOG_STYLE & ~ wx.CAPTION)
        self.this = pre.this
        self.freq = freq
        self.weeksched = weeksched

        p = wx.Panel(self, -1)
        outerbox = wx.BoxSizer(wx.VERTICAL)
        vertsizer = wx.BoxSizer(wx.VERTICAL)

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        self.okbtn = wx.Button(p, -1, _('OK'), style = wx.BU_EXACTFIT)
        smallfont = self.okbtn.GetFont()
        smallfont.SetPointSize(7)
        self.okbtn.SetFont(smallfont)
        self.okbtn.SetDefault()
        self.cancelbtn = wx.Button(p, -1, _('Cancel'), style = wx.BU_EXACTFIT)
        self.SetEscapeId(self.cancelbtn.GetId())
        self.cancelbtn.SetFont(smallfont)
        self.Bind(wx.EVT_BUTTON, self.onOK, self.okbtn)
        self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelbtn)
        buttonbox.Add(self.okbtn)
        buttonbox.Add(self.cancelbtn, 0, wx.LEFT, 5)

        changefreqbox = wx.StaticBoxSizer(wx.StaticBox(p, -1, ''), wx.VERTICAL)

        rbonetime = wx.RadioButton(p, -1, _('One time only'), style = wx.RB_GROUP)
        self.rbdaily = wx.RadioButton(p, -1, _('Daily'))
        self.rbweekly = wx.RadioButton(p, -1, _('Weekly'))
        self.rbweeklymulti = wx.RadioButton(p, -1, _('Weekly on days'))
        if self.freq == 'once':
            rbonetime.SetValue(True)
        elif self.freq == 'daily':
            self.rbdaily.SetValue(True)
        elif self.freq == 'weekly':
            self.rbweekly.SetValue(True)
        elif self.freq == 'weeklymulti':
            self.rbweeklymulti.SetValue(True)

        changefreqbox.Add(rbonetime, 0, wx.TOP, 2)
        changefreqbox.Add(self.rbdaily, 0, wx.TOP, 3)
        changefreqbox.Add(self.rbweekly, 0, wx.TOP, 3)
        changefreqbox.Add(self.rbweeklymulti, 0, wx.TOP, 3)

        daybtnsizer = wx.BoxSizer(wx.HORIZONTAL)
        smallbtnheight = self.okbtn.GetSizeTuple()[1]
        self.daybtns = []
        for i in xrange(7):
            self.daybtns.append(wx.ToggleButton(p, -1, str(i+1), size = (smallbtnheight, smallbtnheight), style = wx.BU_EXACTFIT))
            self.daybtns[i].SetValue(self.weeksched[i] == '1')
            self.daybtns[i].SetFont(smallfont)
            daybtnsizer.Add(self.daybtns[i])

        changefreqbox.Add(daybtnsizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, 3)

        vertsizer.Add(changefreqbox)

        vertsizer.Add(buttonbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 5)

        outerbox.Add(vertsizer, 0, wx.LEFT | wx.RIGHT, 5)

        p.SetAutoLayout(True)
        p.SetSizerAndFit(outerbox)
        self.SetClientSize(p.GetSize())

    def onOK(self, event):
        if self.rbdaily.GetValue():
            self.freq = 'daily'
        elif self.rbweekly.GetValue():
            self.freq = 'weekly'
        elif self.rbweeklymulti.GetValue():
            self.freq = 'weeklymulti'
        else:
            self.freq = 'once'
        self.weeksched = ''
        for i in range(7):
            self.weeksched += str(int(self.daybtns[i].GetValue()))
        self.EndModal(wx.ID_OK)

    def onCancel(self, event):
        self.EndModal(wx.ID_CANCEL)


class ChangeDateDialog(wx.Dialog):
    def __init__(self, parent, ID, datetime, pos):
        pre = wx.PreDialog()
        pre.Create(parent, ID, '', pos, (-1, -1), wx.DEFAULT_DIALOG_STYLE & ~ wx.CAPTION)
        self.this = pre.this
        self.datetime = datetime

        p = wx.Panel(self, -1)
        outerbox = wx.BoxSizer(wx.VERTICAL)
        vertsizer = wx.BoxSizer(wx.VERTICAL)

        changedatebox = wx.StaticBoxSizer(wx.StaticBox(p, -1, ''), wx.HORIZONTAL)

        self.dp = wx.DatePickerCtrl(p, size = (-1, -1), dt = datetime, style = wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)

        changedatebox.Add(self.dp, 1, wx.TOP, 2)

        vertsizer.Add(changedatebox)

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        self.okbtn = wx.Button(p, -1, _('OK'), style = wx.BU_EXACTFIT)
        deffont = self.okbtn.GetFont()
        deffont.SetPointSize(7)
        self.okbtn.SetFont(deffont)
        self.okbtn.SetDefault()
        self.cancelbtn = wx.Button(p, -1, _('Cancel'), style = wx.BU_EXACTFIT)
        self.SetEscapeId(self.cancelbtn.GetId())
        self.cancelbtn.SetFont(deffont)
        self.Bind(wx.EVT_BUTTON, self.onOK, self.okbtn)
        self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelbtn)
        buttonbox.Add(self.okbtn)
        buttonbox.Add(self.cancelbtn, 0, wx.LEFT, 5)

        vertsizer.Add(buttonbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 5)

        outerbox.Add(vertsizer, 0, wx.LEFT | wx.RIGHT, 5)

        p.SetAutoLayout(True)
        p.SetSizerAndFit(outerbox)
        self.SetClientSize(p.GetSize())

    def onOK(self, event):
        self.datetime = self.dp.GetValue()
        self.EndModal(wx.ID_OK)

    def onCancel(self, event):
        self.EndModal(wx.ID_CANCEL)


class ChangeTimeDialog(wx.Dialog):
    def __init__(self, parent, ID, datetime, pos):
        pre = wx.PreDialog()
        pre.Create(parent, ID, '', pos, (-1, -1), wx.DEFAULT_DIALOG_STYLE & ~ wx.CAPTION)
        self.this = pre.this
        self.datetime = datetime

        p = wx.Panel(self, -1)
        outerbox = wx.BoxSizer(wx.VERTICAL)
        vertsizer = wx.BoxSizer(wx.VERTICAL)

        changetimebox = wx.StaticBoxSizer(wx.StaticBox(p, -1, ''), wx.HORIZONTAL)

        self.tc = masked.TimeCtrl(p, -1, fmt24hr = True)
        #self.tc.SetFont(parent.commandlist.GetFont())

        h = self.tc.GetSize().height
        spin = wx.SpinButton(p, -1, (-1, -1), (h * 2 / 3, h), wx.SP_VERTICAL)
        self.tc.BindSpinButton(spin)
        self.tc.SetValue(datetime)

        changetimebox.Add(self.tc, 0, wx.TOP, 2)
        changetimebox.Add(spin, 0, wx.TOP | wx.ALIGN_CENTRE_VERTICAL, 2)

        vertsizer.Add(changetimebox)

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        self.okbtn = wx.Button(p, -1, _('OK'), style = wx.BU_EXACTFIT)
        deffont = self.okbtn.GetFont()
        deffont.SetPointSize(7)
        self.okbtn.SetFont(deffont)
        self.okbtn.SetDefault()
        self.cancelbtn = wx.Button(p, -1, _('Cancel'), style = wx.BU_EXACTFIT)
        self.SetEscapeId(self.cancelbtn.GetId())
        self.cancelbtn.SetFont(deffont)
        self.Bind(wx.EVT_BUTTON, self.onOK, self.okbtn)
        self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelbtn)
        buttonbox.Add(self.okbtn)
        buttonbox.Add(self.cancelbtn, 0, wx.LEFT, 5)

        vertsizer.Add(buttonbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 5)

        outerbox.Add(vertsizer, 0, wx.LEFT | wx.RIGHT, 5)

        p.SetAutoLayout(True)
        p.SetSizerAndFit(outerbox)
        self.SetClientSize(p.GetSize())

    def onOK(self, event):
        self.datetime = self.tc.GetWxDateTime()
        self.EndModal(wx.ID_OK)

    def onCancel(self, event):
        self.EndModal(wx.ID_CANCEL)


class ChangeEndDateDialog(wx.Dialog):
    def __init__(self, parent, ID, datetime, pos):
        pre = wx.PreDialog()
        pre.Create(parent, ID, '', pos, (-1, -1), wx.DEFAULT_DIALOG_STYLE & ~ wx.CAPTION)
        self.this = pre.this
        self.datetime = datetime

        p = wx.Panel(self, -1)
        outerbox = wx.BoxSizer(wx.VERTICAL)
        vertsizer = wx.BoxSizer(wx.VERTICAL)

        changedatebox = wx.StaticBoxSizer(wx.StaticBox(p, -1, ''), wx.VERTICAL)

        rbnoenddate = wx.RadioButton(p, -1, _('No end date'), style = wx.RB_GROUP)
        self.rbenddate = wx.RadioButton(p, -1, '')
        if self.datetime is None:
            rbnoenddate.SetValue(True)
        else:
            self.rbenddate.SetValue(True)

        changedatebox.Add(rbnoenddate, 0, wx.TOP, 2)

        enddatesizer = wx.BoxSizer(wx.HORIZONTAL)

        enddatesizer.Add(self.rbenddate, 0, wx.ALIGN_CENTER_VERTICAL)

        self.dp = wx.DatePickerCtrl(p, size = (-1, -1), style = wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)
        self.dp.Bind(wx.EVT_DATE_CHANGED, self.onChangeDate)
        if datetime is not None:
            self.dp.SetValue(datetime)

        enddatesizer.Add(self.dp, 1, wx.LEFT, 5)

        changedatebox.Add(enddatesizer, 0, wx.TOP, 3)

        vertsizer.Add(changedatebox)

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        self.okbtn = wx.Button(p, -1, _('OK'), style = wx.BU_EXACTFIT)
        deffont = self.okbtn.GetFont()
        deffont.SetPointSize(7)
        self.okbtn.SetFont(deffont)
        self.okbtn.SetDefault()
        self.cancelbtn = wx.Button(p, -1, _('Cancel'), style = wx.BU_EXACTFIT)
        self.SetEscapeId(self.cancelbtn.GetId())
        self.cancelbtn.SetFont(deffont)
        self.Bind(wx.EVT_BUTTON, self.onOK, self.okbtn)
        self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelbtn)
        buttonbox.Add(self.okbtn)
        buttonbox.Add(self.cancelbtn, 0, wx.LEFT, 5)

        vertsizer.Add(buttonbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 5)

        outerbox.Add(vertsizer, 0, wx.LEFT | wx.RIGHT, 5)

        p.SetAutoLayout(True)
        p.SetSizerAndFit(outerbox)
        self.SetClientSize(p.GetSize())

    def onChangeDate(self, event):
        self.rbenddate.SetValue(True)

    def onOK(self, event):
        if self.rbenddate.GetValue():
            self.datetime = self.dp.GetValue()
        else:
            self.datetime = None
        self.EndModal(wx.ID_OK)

    def onCancel(self, event):
        self.EndModal(wx.ID_CANCEL)


class ChangeValueDialog(wx.Dialog):
    def __init__(self, parent, ID, value, pos):
        pre = wx.PreDialog()
        pre.Create(parent, ID, '', pos, (-1, -1), wx.DEFAULT_DIALOG_STYLE & ~ wx.CAPTION)
        self.this = pre.this
        self.value = value

        p = wx.Panel(self, -1)
        outerbox = wx.BoxSizer(wx.VERTICAL)
        
        vertsizer = wx.BoxSizer(wx.VERTICAL)

        changevaluebox = wx.StaticBoxSizer(wx.StaticBox(p, -1, ''), wx.HORIZONTAL)
        self.valuebox = wx.SpinCtrl(p, size = (75,-1))
        self.valuebox.SetRange(0, 99999)
        self.valuebox.SetValue(self.value)
        changevaluebox.Add(self.valuebox, 0, wx.TOP, 2)

        vertsizer.Add(changevaluebox)

        buttonbox = wx.BoxSizer(wx.HORIZONTAL)
        self.okbtn = wx.Button(p, -1, _('OK'), style = wx.BU_EXACTFIT)
        deffont = self.okbtn.GetFont()
        deffont.SetPointSize(7)
        self.okbtn.SetFont(deffont)
        self.okbtn.SetDefault()
        self.cancelbtn = wx.Button(p, -1, _('Cancel'), style = wx.BU_EXACTFIT)
        self.SetEscapeId(self.cancelbtn.GetId())
        self.cancelbtn.SetFont(deffont)
        self.Bind(wx.EVT_BUTTON, self.onOK, self.okbtn)
        self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelbtn)
        buttonbox.Add(self.okbtn)
        buttonbox.Add(self.cancelbtn, 0, wx.LEFT, 5)

        vertsizer.Add(buttonbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 5)

        outerbox.Add(vertsizer, 0, wx.LEFT | wx.RIGHT, 5)

        p.SetAutoLayout(True)
        p.SetSizerAndFit(outerbox)
        self.SetClientSize(p.GetSize())

    def onOK(self, event):
        self.value = int(self.valuebox.GetValue())
        self.EndModal(wx.ID_OK)

    def onCancel(self, event):
        self.EndModal(wx.ID_CANCEL)
